/**
 * Copyright (c) 2019-2029, wwww.kiwipeach.cn (liuburu@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * https://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package cn.kiwipeach.blog.service.impl;

import cn.kiwipeach.blog.base.AjaxResponse;
import cn.kiwipeach.blog.database.domain.*;
import cn.kiwipeach.blog.database.generator.domain.SysFunction;
import cn.kiwipeach.blog.database.mapper.CustomSysFunctionMapper;
import cn.kiwipeach.blog.service.ISysFunctionService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import open.kiwipeach.autoconfigure.shiro.token.AccessToken;
import open.kiwipeach.autoconfigure.web.utils.UserUtil;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 描述：系统菜单接口服务类
 *
 * @author kiwipeach
 * @since 2.0
 */
@Service
@Slf4j
public class SysFunctionServiceImpl extends ServiceImpl<CustomSysFunctionMapper, SysFunction> implements ISysFunctionService {
    /**
     * 系统公共的路由菜单信息
     */
    public static List<SysFunction> PUBLIC_SYS_FUNCTION = new ArrayList<>();

    static {
        // 公共的404跳转
        SysFunction default404Funcion = new SysFunction();
        default404Funcion.setId(UUID.randomUUID().toString().replace("-", ""));
        default404Funcion.setModule("system");
        default404Funcion.setLocation("*");
        default404Funcion.setRedirect("/404");
        default404Funcion.setCode("");
        default404Funcion.setParentid("0");
        PUBLIC_SYS_FUNCTION.add(default404Funcion);
    }

    @Override
    public AjaxResponse<List<VueRouterMenue>> loadSystemMenue() {
        List<SysFunction> filterResultMenue = new ArrayList<>();
        // 加载所有的菜单列表（最好缓存起来）
        QueryWrapper<SysFunction> sysFunctionQueryWrapper = new QueryWrapper<SysFunction>().orderByAsc("weight");
        List<SysFunction> allMenue = list(sysFunctionQueryWrapper);
        // 加载用户角色，并判断是否存在特殊角色（user,admin），如果有则加载内置角色菜单，没有则进行正常角色菜单过滤
        AccessToken currentUser = UserUtil.getCurrentUser();
        List<RolePermissionVO> rolePermissions = currentUser.getRolePermissions();
        List<PermissionVO> permissionVOList = getAllPermissions(rolePermissions);
        List<String> roleSet = rolePermissions.stream().map(p -> p.getRoleName()).collect(Collectors.toList());
        if (roleSet.contains("admin")) {
            filterResultMenue = allMenue.stream().filter(menueItem -> "system".equals(menueItem.getModule()) && "PAGE".equals(menueItem.getNodeType())).collect(Collectors.toList());
        } else if (roleSet.contains("user")) {
            filterResultMenue = allMenue.stream().filter(menueItem -> "blog".equals(menueItem.getModule()) && "PAGE".equals(menueItem.getNodeType())).collect(Collectors.toList());
        } else {
            // 通过用户角色过滤菜单列表（无需权限的菜单、拥有权限的菜单）
            List<String> permissionSet = permissionVOList.stream().map(p -> p.getCode()).collect(Collectors.toList());
            filterResultMenue = allMenue.stream().filter(menueItem -> permissionSet.contains(menueItem.getCode()) && "PAGE".equals(menueItem.getNodeType())).collect(Collectors.toList());
        }
        // 添加默认后台公共路由
        filterResultMenue.addAll(PUBLIC_SYS_FUNCTION);
        // 构建菜单树
        List<SystemMenueVO> systemMenueVOS = filterResultMenue.stream().map(m -> JSON.parseObject(JSON.toJSONString(m), SystemMenueVO.class)).collect(Collectors.toList());
        List<SystemMenueVO> systemMenueTree = wrapperSystemMenueToTree(systemMenueVOS);
        List<VueRouterMenue> vueRouterMenue = wrapperVueRouterMenueTree(systemMenueTree);
        return AjaxResponse.success(vueRouterMenue);
    }

    /**
     * 转换成vue能够识别的路由菜单
     *
     * @param systemMenueTree 系统菜单树
     * @return 返回vue路由树
     */
    private List<VueRouterMenue> wrapperVueRouterMenueTree(List<SystemMenueVO> systemMenueTree) {
        List<VueRouterMenue> vueRouterMenues = new ArrayList<>();
        for (SystemMenueVO menue : systemMenueTree) {
            VueRouterMenue vurRouterItem = transferSystemMenueVO2VueRouterMenue(menue);
            vueRouterMenues.add(vurRouterItem);
            List<SystemMenueVO> children = menue.getChildren();
            if (null != children && children.size() > 0) {
                vurRouterItem.getChildren().addAll(wrapperVueRouterMenueTree(children));
            }
        }
        return vueRouterMenues;
    }

    /**
     * 转换系统菜单成vue路由菜单
     *
     * @param menue 系统菜单
     * @return vue路由菜单
     */
    private VueRouterMenue transferSystemMenueVO2VueRouterMenue(SystemMenueVO menue) {
        VueRouterMenue vueMenue = new VueRouterMenue(menue.getLocation(), menue.getName());
        vueMenue.setRedirect(menue.getRedirect());
        vueMenue.setHidden(Boolean.parseBoolean(menue.getHide()));
        vueMenue.setHideChildrenInMenu(Boolean.parseBoolean(menue.getHideChildreniNmenu()));
        vueMenue.setComponentPath(menue.getComponent());
        MetaVO mata = new MetaVO();
        mata.setTitle(menue.getText())
                .setIcon(menue.getIcon())
                .setKeepAlive(Boolean.parseBoolean(menue.getKeepAlive()))
                .setPermission(menue.getCode().split(","));
        vueMenue.setMeta(mata);
        return vueMenue;
    }

    /**
     * 获取所有的角色几何信息
     *
     * @param rolePermissions 角色权限信息
     * @return 返回所有的权限信息
     */
    private List<PermissionVO> getAllPermissions(List<RolePermissionVO> rolePermissions) {
        List<PermissionVO> resultPermission = new ArrayList<>();
        for (RolePermissionVO role : rolePermissions) {
            resultPermission.addAll(role.getPermissions());
        }
        return resultPermission;
    }

    /**
     * 循环构建树形菜单
     *
     * @param filterResultMenue 过滤好的菜单
     */
    private List<SystemMenueVO> wrapperSystemMenueToTree(List<SystemMenueVO> filterResultMenue) {
        List<SystemMenueVO> trees = new ArrayList<>();
        for (SystemMenueVO curMenueItem : filterResultMenue) {
            // 当前节点为根节点
            if ("0".equals(curMenueItem.getParentid())) {
                trees.add(curMenueItem);
            }
            // 以当前节点为参照，寻找子节点（可能有多个子节点）,并让子节点指向自身
            for (SystemMenueVO item : filterResultMenue) {
                if (item.getParentid().equals(curMenueItem.getId())) {
                    curMenueItem.getChildren().add(item);
                }
            }

        }
        return trees;
    }
}
